/**
 * Copyright (C) 2021 - 2031 O-Cubes Co., Ltd.
 */

/****************************************************************
 *  @file    irq.h
 *  @brief   IRQ header file
 *  @version v1.0
 *  @date    03. Apr. 2023
 ****************************************************************/

#ifndef __IRQ_H__
#define __IRQ_H__

#include <stdbool.h>
#include <stdint.h>
#include "eocv100.h"
#include "core.h"

#ifdef __cplusplus
extern "C" {
#endif

#define CLINT_IRQ_NUM        16
#define CLIC_IRQ_NUM         128

#define INT_TRI_ATTR_POS         1
#define INT_TRI_ATTR_LEN         2
#define INT_SHV_ATTR_POS         0
#define INT_SHV_ATTR_LEN         1



enum irq_tri_attr {
	IRQ_ATTR_LEVEL = 0,
	IRQ_ATTR_RISING_EDGE = 1,
	IRQ_ATTR_FALLING_EDGE = 3,
};

enum irq_shv_attr {
	IRQ_SHV_ATTR_DISABLE = 0,
	IRQ_SHV_ATTR_ENABLE = 1,
};


typedef struct irq_handle irq_handle_t;

typedef void (*irq_handler) (void *ptr);

struct irq_handle {
	irq_handler handler;
	void *priv;
};

/**
 * Enable irq.
 */
__ALWAYS_STATIC_INLINE void irq_enable(uint32_t irq_num)
{
#if defined(CONFIG_SYSTEM_SECURE)
	clic_enable_sirq((int32_t)irq_num);
#else
	clic_enable_irq((int32_t)irq_num);
#endif
}

/**
 * Disable irq.
 */
__ALWAYS_STATIC_INLINE void irq_disable(uint32_t irq_num)
{
#if defined(CONFIG_SYSTEM_SECURE)
	clic_disable_sirq(irq_num);
#else
	clic_disable_irq(irq_num);
#endif
}

/**
 * Configure irq attribute.
 */
void irq_cfg_attr(uint32_t irq_num, enum irq_tri_attr attr);

/**
 * Attach irq handler.
 */
void irq_attach(uint32_t irq_num, irq_handler handler, void *priv);

/**
 * detach irq handler.
 */
void irq_detach(uint32_t irq_num);

/**
 * Set irq priority
 */
__ALWAYS_STATIC_INLINE void irq_set_priority(uint32_t irq_num, uint32_t priority)
{
	clic_set_prio((int32_t)irq_num, priority);
}

/**
 * Gets whether the interrupt is enabled
 */
static inline bool irq_is_enabled(uint32_t irq_num)
{
	return (clic_get_enabled_irq((int32_t)irq_num) > 0) ? true : false;
}

static inline uint32_t irq_get_irq_num(void)
{
	return (__get_MCAUSE() & 0x3FF);
}

/**
 * Gets whether in irq context
 */
bool is_in_irq_context(void);

/**
 * Dispatching irq handlers
 */
void do_irq(void);

void SystemInit(void);

#ifdef __cplusplus
}
#endif

#endif /* __IRQ_H__ */

